package com.demo;

import javax.sql.DataSource;

import org.apache.commons.lang3.StringUtils;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import com.baomidou.mybatisplus.extension.plugins.PaginationInterceptor;

@Configuration
public class DataSourceConfig {

	@Bean
    public PaginationInterceptor paginationInterceptor() {
        return new PaginationInterceptor();
    }

	@Bean("buildDataSource")
	public static DataSource buildDataSource() {
		String propertyFile = "jdbc.properties";
		String prefix = "commonds";
    	String driverClassName = PropertiesInnerUtil.getString(propertyFile, prefix + ".datasource.driverClassName");
    	String url = PropertiesInnerUtil.getString(propertyFile, prefix + ".datasource.url");
    	String username = PropertiesInnerUtil.getString(propertyFile, prefix + ".datasource.username");
    	String password = PropertiesInnerUtil.getString(propertyFile, prefix + ".datasource.password");
    	String type = PropertiesInnerUtil.getString(propertyFile, prefix + ".datasource.type");
    	try {
            Class<? extends DataSource> dataSourceType = (Class<? extends DataSource>) Class.forName(type);
            try {
				Object dsObj = dataSourceType.newInstance();
				return initProp(dsObj, driverClassName, url, username, password, propertyFile, prefix);
			} catch (Exception e) {
				e.printStackTrace();
			}
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
        return null;
    }

	private static DataSource initProp(Object dsObj, String driverClassName, String jdbcUrl, String username, String password, String propertyFile, String prefix) {
    	String className = dsObj.getClass().getSimpleName();
    	if(className.equals("HikariDataSource")){
    		try {
				dsObj.getClass().getMethod("setDriverClassName", String.class).invoke(dsObj, driverClassName);
				dsObj.getClass().getMethod("setJdbcUrl", String.class).invoke(dsObj, jdbcUrl);
				dsObj.getClass().getMethod("setUsername", String.class).invoke(dsObj, username);
				dsObj.getClass().getMethod("setPassword", String.class).invoke(dsObj, password);
				dsObj.getClass().getMethod("setMinimumIdle", int.class).invoke(dsObj, PropertiesInnerUtil.getInteger(propertyFile, prefix + ".pool.minimumIdle", 5));
				dsObj.getClass().getMethod("setMaximumPoolSize", int.class).invoke(dsObj, PropertiesInnerUtil.getInteger(propertyFile, prefix + ".pool.maximumPoolSize", 15));
				dsObj.getClass().getMethod("setIdleTimeout", long.class).invoke(dsObj, PropertiesInnerUtil.getLong(propertyFile, prefix + ".pool.idleTimeout", 30000l));
				dsObj.getClass().getMethod("setMaxLifetime", long.class).invoke(dsObj, PropertiesInnerUtil.getLong(propertyFile, prefix + ".pool.maxLifetime", 1800000l));
				dsObj.getClass().getMethod("setConnectionTimeout", long.class).invoke(dsObj, PropertiesInnerUtil.getLong(propertyFile, prefix + ".pool.connectionTimeout", 30000l));
				dsObj.getClass().getMethod("setConnectionTestQuery", String.class).invoke(dsObj, PropertiesInnerUtil.getString(propertyFile, prefix + ".pool.connectionTestQuery", "SELECT 1"));
				if(StringUtils.isNotEmpty(PropertiesInnerUtil.getString(propertyFile, prefix + ".pool.poolName")))
					dsObj.getClass().getMethod("setPoolName", String.class).invoke(dsObj, PropertiesInnerUtil.getString(propertyFile, prefix + ".pool.poolName"));
			} catch (Exception e) {
				e.printStackTrace();
			}
    		return (DataSource)dsObj;
    	}
    	if(className.equals("DruidDataSource")){
    		try {
	    		dsObj.getClass().getMethod("setDriverClassName", String.class).invoke(dsObj, driverClassName);
	    		dsObj.getClass().getMethod("setUrl", String.class).invoke(dsObj, jdbcUrl);
	    		dsObj.getClass().getMethod("setUsername", String.class).invoke(dsObj, username);
	    		dsObj.getClass().getMethod("setPassword", String.class).invoke(dsObj, password);
	    		dsObj.getClass().getMethod("setInitialSize", int.class).invoke(dsObj, PropertiesInnerUtil.getInteger(propertyFile, prefix + ".pool.initialSize", 5));
	    		dsObj.getClass().getMethod("setMinIdle", int.class).invoke(dsObj, PropertiesInnerUtil.getInteger(propertyFile, prefix + ".pool.minIdle", 5));
	    		dsObj.getClass().getMethod("setMaxActive", int.class).invoke(dsObj, PropertiesInnerUtil.getInteger(propertyFile, prefix + ".pool.maxActive", 5));
	    		dsObj.getClass().getMethod("setMaxWait", long.class).invoke(dsObj, PropertiesInnerUtil.getLong(propertyFile, prefix + ".pool.maxWait", 2000l));
	    		dsObj.getClass().getMethod("setTimeBetweenEvictionRunsMillis", long.class).invoke(dsObj, PropertiesInnerUtil.getLong(propertyFile, prefix + ".pool.timeBetweenEvictionRunsMillis", 60000l));
	    		dsObj.getClass().getMethod("setMinEvictableIdleTimeMillis", long.class).invoke(dsObj, PropertiesInnerUtil.getLong(propertyFile, prefix + ".pool.minEvictableIdleTimeMillis", 400000l));
	    		dsObj.getClass().getMethod("setValidationQuery", String.class).invoke(dsObj, PropertiesInnerUtil.getString(propertyFile, prefix + ".pool.validationQuery", "SELECT 1"));
	    		dsObj.getClass().getMethod("setTestWhileIdle", boolean.class).invoke(dsObj, PropertiesInnerUtil.getBoolean(propertyFile, prefix + ".pool.testWhileIdle", true));
	    		dsObj.getClass().getMethod("setTestOnBorrow", boolean.class).invoke(dsObj, PropertiesInnerUtil.getBoolean(propertyFile, prefix + ".pool.testOnBorrow", false));
	    		dsObj.getClass().getMethod("setTestOnReturn", boolean.class).invoke(dsObj, PropertiesInnerUtil.getBoolean(propertyFile, prefix + ".pool.testOnReturn", false));
	    		dsObj.getClass().getMethod("setPoolPreparedStatements", boolean.class).invoke(dsObj, PropertiesInnerUtil.getBoolean(propertyFile, prefix + ".pool.poolPreparedStatements", false));
	    		if(StringUtils.isNotEmpty(PropertiesInnerUtil.getString(propertyFile, prefix + ".pool.filters")))
					dsObj.getClass().getMethod("setFilters", String.class).invoke(dsObj, PropertiesInnerUtil.getString(propertyFile, prefix + ".pool.filters"));
	    		if(StringUtils.isNotEmpty(PropertiesInnerUtil.getString(propertyFile, prefix + ".pool.useGlobalDataSourceStat")))
	    			dsObj.getClass().getMethod("setUseGlobalDataSourceStat", boolean.class).invoke(dsObj, PropertiesInnerUtil.getBoolean(propertyFile, prefix + ".pool.useGlobalDataSourceStat"));
	    		if(StringUtils.isNotEmpty(PropertiesInnerUtil.getString(propertyFile, prefix + ".pool.connectionProperties")))
	    			dsObj.getClass().getMethod("setConnectionProperties", String.class).invoke(dsObj, PropertiesInnerUtil.getString(propertyFile, prefix + ".pool.connectionProperties"));
    		} catch (Exception e) {
    			e.printStackTrace();
			}
    		return (DataSource)dsObj;
    	}
		return (DataSource)dsObj;
	}

}
